//
//  CalendarCollectionViewEditableLayout.m
//  OfficeBook
//
//  Created by 孙晓奇 on 15/10/10.
//  Copyright © 2015年 sunny. All rights reserved.
//

#import "CalendarCollectionViewEditableLayout.h"
#import "CalendarFakeEventCell.h"

typedef NS_ENUM(NSInteger,CellPanType) {
    CellPanTypeNone,
    CellPanTypeBodyPan,
    CellPanTypeLeftPan,
    CellPanTypeRightPan
};

@interface UIImageView (CalendarCollectionViewEditableLayout)

- (void)setViewCopiedImage:(UIView *)view;

@end

@implementation UIImageView (CalendarCollectionViewEditableLayout)

- (void)setViewCopiedImage:(UIView *)view {
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 4.f);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    self.image = image;
}

@end


@interface CalendarCollectionViewEditableLayout()<UIGestureRecognizerDelegate>
@property (nonatomic, assign) UIEdgeInsets scrollTrigerEdgeInsets;
@property (nonatomic, assign) UIEdgeInsets scrollTrigePadding;
@property (nonatomic, assign) NSInteger scrollDirection;
@property (nonatomic, strong) CADisplayLink *displayLink;
@property (nonatomic, assign) BOOL grSetuped;

@property (nonatomic, strong) CalendarFakeEventCell *fakeCell;
@property (nonatomic, strong) UIPanGestureRecognizer *cellFakeBodyPangr;
@property (nonatomic, strong) UIPanGestureRecognizer *cellFakeLeftPangr;
@property (nonatomic, strong) UIPanGestureRecognizer *cellFakeRightPangr;

@property (nonatomic, assign) BOOL cellTouchViewEdge;
@end

@implementation CalendarCollectionViewEditableLayout

#pragma mark - Override methods

- (void)setDelegate:(id<CalendarCollectionViewEditableLayoutDelegate>)delegate
{
    self.collectionView.delegate = delegate;
}

- (id<CalendarCollectionViewEditableLayoutDelegate>)delegate
{
    return (id<CalendarCollectionViewEditableLayoutDelegate>)self.collectionView.delegate;
}

-(instancetype)init {
    self = [super init];
    if (self) {
        self.fakeCell = [[CalendarFakeEventCell alloc] initWithFrame:CGRectZero];
        self.fakeCell.layer.zPosition = 0;
    }
    return self;

}

- (void)prepareLayout
{
    [super prepareLayout];
    //gesture
    [self setUpCollectionViewGestures];
    //scroll triger insets
    self.scrollTrigerEdgeInsets = UIEdgeInsetsMake(0.f, 0.f, 0.f, 10.f);
    //scroll triger padding
    self.scrollTrigePadding = UIEdgeInsetsMake(0, 0, 0, 0);

}

- (void)setUpCollectionViewGestures
{
    if (!self.grSetuped) {
        _longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleCellLongPress:)];
        _longPressGesture.delegate = self;
        [self.collectionView addGestureRecognizer:_longPressGesture];
        
        for (UIGestureRecognizer *gestureRecognizer in self.collectionView.gestureRecognizers) {
            if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
                [gestureRecognizer requireGestureRecognizerToFail:_longPressGesture];
            }
        }
        
        // 点击空白处取消event的选中状态
        // 轻点event处显示详情
        UITapGestureRecognizer *tapgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
        [self.collectionView addGestureRecognizer:tapgr];
        
        self.grSetuped = YES;
    }
}

#pragma mark - Handle Gestures
// 长按
-(void)handleCellLongPress:(UIGestureRecognizer *)uigr {
    NSIndexPath *indexPath;
    static NSInteger cellType;
    if (uigr.state == UIGestureRecognizerStateBegan) {
        indexPath = [self.collectionView indexPathForItemAtPoint:[uigr locationInView:self.collectionView]];
        if (indexPath == nil) {  // new event
            cellType = CalendarCellStatusEnumCreate;
            self.newCellLocation = [uigr locationInView:self.collectionView];
             //!!创建时根据x位置 y需要居中
            //self.newCellLocation = (CGPoint){self.newCellLocation.x, self.contentMargin.top + (self.sectionHeight - self.itemHeight)/2};
            [self.delegate collectionView:self.collectionView createItemAtLocation:self.newCellLocation];
        }
        else {
            cellType = CalendarCellStatusEnumSelected;
            self.currentCell = (CalendarEventCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
            
            // fake cell
            self.fakeCell.frame = self.currentCell.frame;
            [self.fakeCell forkDataFromOtherCell:self.currentCell];
            self.fakeCell.selected = YES;
            [self.collectionView addSubview:self.fakeCell];
            [self.fakeCell cellSelectedAnimation:YES];
            
            if ([self.delegate respondsToSelector:@selector(collectionView:beginLongPressSelectItemAtIndexPath:)]) {
                [self.delegate collectionView:self.collectionView beginLongPressSelectItemAtIndexPath:indexPath];
            }
        }
    }
    else if (uigr.state == UIGestureRecognizerStateEnded){
        
        // cell fake view gestures
        self.cellFakeBodyPangr = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleCellFakeBodyDrag:)];
        self.cellFakeBodyPangr.delegate = self;
        [self.fakeCell.bodyView addGestureRecognizer:self.cellFakeBodyPangr];
        
        self.cellFakeLeftPangr = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleCellFakeLeftDrag:)];
        self.cellFakeLeftPangr.delegate = self;
        [self.fakeCell.leftDrag addGestureRecognizer:self.cellFakeLeftPangr];
        
        self.cellFakeRightPangr = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleCellFakeRightDrag:)];
        self.cellFakeRightPangr.delegate = self;
        [self.fakeCell.rightDrag addGestureRecognizer:self.cellFakeRightPangr];
        
        [self.delegate collectionView:self.collectionView didEndLongPressCell:self.currentCell];
        
    }
}

// 轻点
-(void)handleTap:(UIGestureRecognizer *)uigr {
    NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:[uigr locationInView:self.collectionView]];
    // 点击空白处
    if (indexPath == nil) {
        [self removeFakeCell];
    }
    // 点击event显示详情
    else {
        self.currentCell = (CalendarEventCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
        self.fakeCell.frame = self.currentCell.frame;
        [self.fakeCell forkDataFromOtherCell:self.currentCell];
        self.fakeCell.selected = YES;
//        self.fakeCell.bodyView.backgroundColor = [[UIColor colorWithHexString:@"35b1f1"] colorWithAlphaComponent:0.75f];
        [self.collectionView addSubview:self.fakeCell];
        
        //显示event详情
        [self.delegate collectionView:self.collectionView shouldShowDetailForItemAtIndexPath:indexPath];
    }

}

#pragma mark - handle cell pan gestures

// cell整体拖拽
-(void)handleCellFakeBodyDrag:(UIPanGestureRecognizer *)uigr{
    //NSLog(@"uigr.state: %li", (long)uigr.state);
    static CGRect oldFrame;
    if (uigr.state == UIGestureRecognizerStateBegan) {
        self.fakeCell.frame = self.currentCell.frame;
        oldFrame = self.fakeCell.frame;
        [self.fakeCell cellHidden:NO];
    }
    else if (uigr.state == UIGestureRecognizerStateChanged){
        //NSLog(@"%@", NSStringFromCGRect(self.fakeCell.frame));
        CGPoint translation = [uigr translationInView:self.fakeCell.superview];
        CGAffineTransform theTransform = self.fakeCell.transform;
        theTransform.tx = translation.x;
        theTransform.ty = translation.y;
        self.fakeCell.transform = theTransform;
        
        [self autoScrollIfNeeded];
    }
    else if (uigr.state == UIGestureRecognizerStateEnded) {
        //disable auto scroll
        [self invalidateDisplayLink];

        void (^endOfCellDragBlock)(BOOL) = ^(BOOL finished){
            self.currentCell.frame = self.fakeCell.frame;
            [self.delegate collectionView:self.collectionView didEndDragCell:self.currentCell];
            // !!不能使用[sel.fakeCell setHidden],否则fakecell无法响应手势事件
            //[self.fakeCell cellHidden:YES];
        };
        
        if (self.cellTouchViewEdge == NO) {
            CGPoint newCenter = CGPointMake(self.fakeCell.center.x + self.fakeCell.transform.tx,
                                            self.fakeCell.center.y + self.fakeCell.transform.ty);
            self.fakeCell.center = newCenter;
            
            if (CGRectGetMinY(self.fakeCell.frame) < 0 || CGRectGetMaxY(self.fakeCell.frame) > CGRectGetHeight(self.collectionView.frame)){
                self.fakeCell.center = (CGPoint){self.fakeCell.center.x, self.currentCell.defaultCenterY};
            }
            CGAffineTransform theTransform = self.fakeCell.transform;
            theTransform = CGAffineTransformIdentity;
            self.fakeCell.transform = theTransform;
            endOfCellDragBlock(YES);
        } else {
            [UIView animateWithDuration:0.1f delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
                CGPoint newCenter = CGPointMake(40 + CGRectGetWidth(self.fakeCell.frame)/2, self.fakeCell.center.y + self.fakeCell.transform.ty);
                self.fakeCell.center = newCenter;
                if (CGRectGetMinY(self.fakeCell.frame) < 0 || CGRectGetMaxY(self.fakeCell.frame) > CGRectGetHeight(self.collectionView.frame)){
                    self.fakeCell.center = (CGPoint){self.fakeCell.center.x, self.currentCell.defaultCenterY};
                }
                CGAffineTransform theTransform = self.fakeCell.transform;
                theTransform = CGAffineTransformIdentity;
                self.fakeCell.transform = theTransform;
            } completion:endOfCellDragBlock];
            self.cellTouchViewEdge = NO;
        }
    }
}

// 左边拖拉
-(void)handleCellFakeLeftDrag:(UIPanGestureRecognizer *)uigr {
    static CGRect oldFrame;
    if (uigr.state == UIGestureRecognizerStateBegan) {
        self.fakeCell.frame = self.currentCell.frame;
        oldFrame = self.fakeCell.frame;
        [self.fakeCell cellHidden:NO];
    }
    else if (uigr.state == UIGestureRecognizerStateChanged){
        CGPoint location = [uigr locationInView:self.fakeCell.superview];
        
        CGRect frame = self.fakeCell.frame;
        frame.size.width += frame.origin.x - location.x;
        frame.origin.x = location.x;
        if (frame.size.width < CalendarCellPadding * 4) {
            frame.size.width = CalendarCellPadding * 4;
            frame.origin.x = CGRectGetMaxX(self.fakeCell.frame) - CalendarCellPadding * 4;
        }
        self.fakeCell.frame = frame;
    }
    else if (uigr.state == UIGestureRecognizerStateEnded) {
        self.currentCell.frame = self.fakeCell.frame;
        [self.delegate collectionView:self.collectionView didEndDragCell:self.currentCell];
        //[self.fakeCell cellHidden:YES];
    }
}

// 右边拖拉
-(void)handleCellFakeRightDrag:(UIPanGestureRecognizer *)uigr {
    static CGRect oldFrame;
    if (uigr.state == UIGestureRecognizerStateBegan) {
        oldFrame = self.fakeCell.frame;
        [self.fakeCell cellHidden:NO];
    }
    else if (uigr.state == UIGestureRecognizerStateChanged){
        CGPoint location = [uigr locationInView:self.fakeCell.superview];
        
        CGRect frame = self.fakeCell.frame;
        frame.size.width += location.x - CGRectGetMaxX(frame);
        frame.size.width = MAX(frame.size.width, CalendarCellPadding * 4);
        self.fakeCell.frame = frame;
    }
    else if (uigr.state == UIGestureRecognizerStateEnded) {
        self.currentCell.frame = self.fakeCell.frame;
        [self.delegate collectionView:self.collectionView didEndDragCell:self.currentCell];
        //[self.fakeCell cellHidden:YES];
    }
}

#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    return YES;
}

#pragma mark - auto scroll
-(void)autoScrollIfNeeded {
    //NSLog(@"%f %f %f", self.collectionView.contentInset.left, self.collectionView.contentInset.right, self.collectionView.contentOffset.x);
    //scroll direction
    if (CGRectGetMaxX(self.fakeCell.frame) >= self.collectionView.contentOffset.x + (self.collectionView.bounds.size.width - self.scrollTrigerEdgeInsets.right -self.scrollTrigePadding.right))
    {
        if (ceilf(self.collectionView.contentOffset.x) <= self.collectionView.contentSize.width - self.collectionView.bounds.size.width) {
            self.scrollDirection = ScrollDirctionRight;
            [self setUpDisplayLink];
        }
    }else if (CGRectGetMinX(self.fakeCell.frame) <=
              self.collectionView.contentOffset.x + self.scrollTrigerEdgeInsets.left + self.scrollTrigePadding.left)
    {
        if (self.collectionView.contentOffset.x >= - self.collectionView.contentInset.left) {
            self.scrollDirection = ScrollDirctionLeft;
            [self setUpDisplayLink];
        }
    }else {
        self.scrollDirection = ScrollDirctionNone;
        [self invalidateDisplayLink];
    }
    //NSLog(@"scrollDirection: %li", (long)self.scrollDirection);
}

- (void)setUpDisplayLink
{
    if (_displayLink) {
        return;
    }
    _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(autoScroll)];
    [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}

-  (void)invalidateDisplayLink
{
    [_displayLink invalidate];
    _displayLink = nil;
}

- (void)autoScroll
{
   // NSLog(@"%f %f %f", self.collectionView.contentInset.left, self.collectionView.contentInset.right, self.collectionView.contentOffset.x);
    
    CGPoint contentOffset = self.collectionView.contentOffset;
    UIEdgeInsets contentInset = self.collectionView.contentInset;
    CGSize contentSize = self.collectionView.contentSize;
    CGSize boundsSize = self.collectionView.bounds.size;
    CGFloat increment = 0;
    
    if (self.scrollDirection == ScrollDirctionRight) {
        CGFloat percentage = (((CGRectGetMaxX(self.fakeCell.frame) - contentOffset.x) - (boundsSize.width - _scrollTrigerEdgeInsets.right - _scrollTrigePadding.right)) / _scrollTrigerEdgeInsets.right);
        increment = MIN(10.f, 10 * percentage);
        
    }else if (self.scrollDirection == ScrollDirctionLeft) {
        CGFloat percentage = (1.f - ((CGRectGetMinX(self.fakeCell.frame) - contentOffset.x - _scrollTrigePadding.left) / _scrollTrigerEdgeInsets.left));
        increment = MAX(-10.f, -10.f * percentage);
    }
    
    if (contentOffset.x + increment <= -contentInset.left) {
        self.cellTouchViewEdge = YES;
        [UIView animateWithDuration:.07f delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
            //CGFloat diff = -contentInset.left - contentOffset.x;
            self.collectionView.contentOffset = CGPointMake(-contentInset.left, contentOffset.y);
            //self.fakeCell.center = CGPointMake(44, self.fakeCell.center.y);
        } completion:nil];
        [self invalidateDisplayLink];
        return;
    }else if (contentOffset.x + increment >= contentSize.width - boundsSize.width - contentInset.right) {
        self.cellTouchViewEdge = YES;
        [UIView animateWithDuration:.07f delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
            CGFloat diff = contentSize.width - boundsSize.width - contentInset.right - contentOffset.x;
            self.collectionView.contentOffset = CGPointMake(contentSize.width - boundsSize.width - contentInset.right, contentOffset.y);
            self.fakeCell.center = CGPointMake(self.fakeCell.center.x + diff, self.fakeCell.center.y);
        } completion:nil];
        [self invalidateDisplayLink];
        return;
    }
    
    self.cellTouchViewEdge = NO;
    self.fakeCell.center = CGPointMake(self.fakeCell.center.x + increment, self.fakeCell.center.y);
    self.collectionView.contentOffset = CGPointMake(contentOffset.x + increment, contentOffset.y);
    
}


#pragma mark fakecell methods
- (void)addFakeCell:(CalendarEventCell *)currentCell {
    self.currentCell = currentCell;
    
    self.fakeCell.frame = self.currentCell.frame;
    [self.fakeCell forkDataFromOtherCell:self.currentCell];
    self.fakeCell.selected = YES;
    [self.collectionView addSubview:self.fakeCell];
    [self.fakeCell layoutIfNeeded];      // !!!important
    
    [self.fakeCell cellCreatedAnimation:YES];
    
    self.newCellLocation = (CGPoint){-1, -1};
}

-(void)removeFakeCell {
    [self.fakeCell.bodyView removeGestureRecognizer:self.cellFakeBodyPangr];
    [self.fakeCell.leftDrag removeGestureRecognizer:self.cellFakeLeftPangr];
    [self.fakeCell.rightDrag removeGestureRecognizer:self.cellFakeRightPangr];
    [self.fakeCell removeFromSuperview];
    [self invalidateDisplayLink];
}

// !!!
// cell adjustItemsForOverlap方法会导致fakecell 和realcell frame不统一.
// 因此当real cell更新后即将显示时, 需要同时更新fakecell, 使两者完全重叠.
-(void)adjustFakeCell:(CalendarEventCell *)currentCell{
    self.currentCell = currentCell;
    self.fakeCell.frame = self.currentCell.frame;
    [self.fakeCell forkDataFromOtherCell:self.currentCell];
    [self.fakeCell layoutIfNeeded];
}

@end
